package com.cheems.cheems_spring_ai.controller;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import com.auth0.jwt.interfaces.Claim;
import com.cheems.cheems_spring_ai.common.BaseResponse;
import com.cheems.cheems_spring_ai.common.ErrorCode;
import com.cheems.cheems_spring_ai.common.ResultUtils;
import com.cheems.cheems_spring_ai.config.Tools;
import com.cheems.cheems_spring_ai.domain.AiOperation;
import com.cheems.cheems_spring_ai.domain.dto.AiRequestDTO;
import com.cheems.cheems_spring_ai.domain.vo.ConversationHistoryVO;
import com.cheems.cheems_spring_ai.domain.vo.ConversationVO;
import com.cheems.cheems_spring_ai.exception.BusinessException;
import com.cheems.cheems_spring_ai.service.AiOperationService;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.AbstractChatMemoryAdvisor;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.ai.chat.model.ChatResponse;
import org.springframework.ai.chat.messages.Message;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.ai.chat.messages.SystemMessage;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.ollama.OllamaChatModel;
import org.springframework.ai.ollama.api.OllamaModel;
import org.springframework.ai.ollama.api.OllamaOptions;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;

import static com.cheems.cheems_spring_ai.utils.JwtUtil.verifyToken;

@Slf4j
@RestController
@RequestMapping("/api/ai")
public class AIController {

    @Resource
    private ChatClient chatClient;

    @Resource
    private Tools tools;

    @Resource
    private AiOperationService aiOperationService;
    
    /**
     * 获取用户的所有会话ID和最后一条数据（最多返回最近的5条会话记录）
     * @param request 请求信息
     * @return 会话信息列表
     */
    @GetMapping("/conversations")
    public BaseResponse<List<ConversationVO>> getUserConversations(HttpServletRequest request) {
        // 获取用户信息
        String token = request.getHeader("Authorization");
        log.info("token: " + token);
        if (token == null) {
            throw new BusinessException(ErrorCode.NOT_LOGIN_ERROR);
        }
        Map<String, Claim> stringClaimMap = verifyToken(token);
        if (stringClaimMap == null) {
            throw new BusinessException(ErrorCode.TOKEN_INVALID, "无效令牌");
        }
        String henauNumber = stringClaimMap.get("henauNumber").asString();
        
        // 获取用户的所有会话及最后一条消息（最多5条）
        List<ConversationVO> conversations = aiOperationService.getUserConversations(henauNumber);
        return ResultUtils.success(conversations);
    }
    
    /**
     * 根据会话ID获取对话历史记录
     * @param conversationId 会话ID
     * @param request 请求信息
     * @return 对话历史记录列表
     */
    @GetMapping("/conversation")
    public BaseResponse<List<ConversationHistoryVO>> getConversationHistory(
            @RequestParam String conversationId,
            HttpServletRequest request) {
        // 获取用户信息
        String token = request.getHeader("Authorization");
        if (token == null) {
            throw new BusinessException(ErrorCode.NOT_LOGIN_ERROR);
        }
        Map<String, Claim> stringClaimMap = verifyToken(token);
        if (stringClaimMap == null) {
            throw new BusinessException(ErrorCode.TOKEN_INVALID, "无效令牌");
        }
        String henauNumber = stringClaimMap.get("henauNumber").asString();
        if (henauNumber == null) {
            throw new BusinessException(ErrorCode.TOKEN_INVALID, "令牌缺少必要声明");
        }
        
        // 获取指定会话的所有对话记录
        List<ConversationHistoryVO> historyList = aiOperationService.getConversationHistoryById(conversationId, henauNumber);
        return ResultUtils.success(historyList);
    }
    
    /**
     * 创建新会话
     * @return 新会话ID
     */
    @PostMapping("/conversation/new")
    public BaseResponse<String> createNewConversation() {
        String conversationId = aiOperationService.createNewConversation();
        return ResultUtils.success(conversationId);
    }
    
    /**
     * 获取流式数据
     * @return
     */
    @PostMapping(value = "/stream")
    public Flux<String> stream(@RequestBody AiRequestDTO aiRequestDTO, HttpServletRequest request) {
        // 记录开始时间
        long startTime = System.currentTimeMillis();

        // 提前获取所有需要的请求信息，避免在异步处理中使用request
        String remoteAddr = request.getRemoteAddr();
        String userAgent = request.getHeader("User-Agent");
        
        // 获取用户信息
        String token = request.getHeader("Authorization");
        if (token == null) {
            throw new BusinessException(ErrorCode.NOT_LOGIN_ERROR);
        }
        Map<String, Claim> stringClaimMap = verifyToken(token);
        if (stringClaimMap == null) {
            throw new BusinessException(ErrorCode.TOKEN_INVALID, "无效令牌");
        }
        String henauNumber = stringClaimMap.get("henauNumber").asString();
        String userName = stringClaimMap.get("userName").asString();
        
        // 创建日志对象
        AiOperation aiOperation = new AiOperation();
        aiOperation.setHenauNumber(henauNumber);
        aiOperation.setUserName(userName);
        
        // 处理会话ID
        String conversationId = aiRequestDTO.getConversationId();
        if (conversationId == null || aiRequestDTO.getOperationType() == 0) {
            // 如果是新建对话，创建新会话ID
            conversationId = aiOperationService.createNewConversation();
        }
        aiOperation.setConversationId(conversationId);
        
        // 初始化提示词构建器
        ChatClient.ChatClientRequestSpec prompt = chatClient.prompt();

        // 用户消息内容，根据操作类型决定是否包含历史对话
        StringBuilder userContent = new StringBuilder();
        
        // 如果操作类型为2（继续对话且加载历史），则获取历史对话并添加到用户消息中
        if (aiRequestDTO.getOperationType() != null && aiRequestDTO.getOperationType() == 2) {
            List<AiOperation> historyOperations = aiOperationService.getHistoryByConversationId(conversationId);
            
            if (!historyOperations.isEmpty()) {
                userContent.append("以下是我之前的对话历史:\n\n");
                
                for (AiOperation history : historyOperations) {
                    userContent.append("用户: ").append(history.getUserInput()).append("\n");
                    userContent.append("助手: ").append(history.getAiOutput()).append("\n\n");
                }
                
                userContent.append("基于以上对话历史，请回答我的问题：\n");
            }
        }
        
        // 添加用户当前的问题
        userContent.append(aiRequestDTO.getMessage());
        
        Flux<String> flux = prompt
                // 用户信息（包含历史对话内容和当前问题）
                .user(userContent.toString())
                // 添加toolcalling，IOC容器管理Bean对象
                //.tools(tools)
                .stream()
                // 响应
                .content();
        
        // 创建一个新的Flux，用于收集并记录完整的AI响应
        Flux<String> recordedFlux = flux.cache();
        
        // 异步收集完整响应并保存到数据库
        recordedFlux.collectList().subscribe(list -> {
            try {
                // 记录完整输出
                aiOperation.setUserInput(aiRequestDTO.getMessage());
                aiOperation.setAiOutput(String.join("", list));
                aiOperation.setCreateTime(new Date());
                // 使用提前获取的请求信息
                aiOperation.setIp(remoteAddr);
                aiOperation.setUa(userAgent);
                // 记录结束时间并计算耗时
                long endTime = System.currentTimeMillis();
                aiOperation.setCostTime(String.valueOf(endTime - startTime));
                aiOperation.setUseModel("deepseek-r1:32b");
                aiOperation.setAppId(0L);
                aiOperation.setAppName("");
                aiOperation.setModelId(0L);
                aiOperation.setModelName("");
                
                // 保存到数据库
                aiOperationService.save(aiOperation);
            } catch (Exception e) {
                // 记录异常，但不影响响应流
                log.error("保存AI操作记录失败", e);
            }
        });
        
        // 返回原始流，不影响客户端响应
        return recordedFlux;
    }
}